package com.yanqu.road.logic.activity.suitang;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yanqu.road.utils.string.StringUtils;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class SuiTangMapLogic {

    /**
     * 地图数据，找客户端要
     */
    public static String MAP_PARAM = "{\"cityLink\":[4001,6001,4,1001,2002,3,1001,2003,3,1005,2012,3,1005,2013,3,1002,2014,3,1002,2015,3,1011,2022,3,1011,2023,3,1004,2020,3,1004,2021,3,1008,2018,3,1008,2019,3,1009,2016,3,1009,2017,3,1003,2008,3,1003,2009,3,1012,2010,3,1012,2011,3,2001,3001,4,2001,2002,2,2001,2024,3,2002,3001,4,2002,2003,3,2003,4001,3,2003,6001,2,2003,2004,3,2004,4001,3,2004,6001,3,2004,2005,3,2005,4001,3,2005,2006,3,2006,4001,3,2006,2007,3,2007,3004,4,2007,2008,3,2008,3004,4,2008,2009,3,2009,4003,3,2009,2010,3,2010,4003,3,2010,2011,3,2011,4003,3,2011,2012,3,2012,4003,3,2012,2013,3,2013,3003,4,2013,2014,2,2014,3003,4,2014,2015,3,2015,4002,3,2015,2016,3,2016,4002,3,2016,2017,3,2017,4002,3,2017,2018,3,2018,4002,3,2018,2019,3,2019,3002,4,2019,2020,3,2020,3002,4,2020,2021,3,2021,4004,3,2021,2022,3,2022,4004,3,2022,2023,3,2023,4004,3,2023,2024,3,2024,4004,3,2025,5001,2,2025,4004,3,2025,3002,2,2026,5001,2,2026,4001,3,2026,3001,2,2027,5001,2,2027,4003,3,2027,3004,2,2028,5001,2,2028,4002,3,2028,3003,2,1010,2004,3,1010,2005,3,1007,2006,3,1007,2007,3,1006,2001,3,1006,2024,3]}";

    public static Map<String, Integer> costSoFar = new HashMap<>();

    // =============================

    /**
     * 生成地图
     *
     * @return 地点，相邻地点List
     */
    public static Map<Integer, List<Integer>> getCityConnectMapConfig() {
        String mapParam = MAP_PARAM;
        Map<Integer, List<Integer>> listMap = new ConcurrentHashMap<>();

        JSONObject jsonObject = JSONObject.parseObject(mapParam);
        JSONArray cityLink = jsonObject.getJSONArray("cityLink");
        Integer[] keyArr = new Integer[cityLink.size()];
        keyArr = cityLink.toArray(keyArr);
        List<Integer> list = new ArrayList<>(Arrays.asList(keyArr));
        for (int i = 0; i < list.size() && i + 1 < list.size() && i + 2 < list.size(); i = i + 3) {
            int cityA = list.get(i);
            int cityB = list.get(i + 1);
            int distance = list.get(i + 2);

            listMap.putIfAbsent(cityA, new ArrayList<>());
            listMap.get(cityA).add(cityB);
            costSoFar.put(cityA + "_" + cityB, distance);

            listMap.putIfAbsent(cityB, new ArrayList<>());
            listMap.get(cityB).add(cityA);
            costSoFar.put(cityB + "_" + cityA, distance);
        }

        return listMap;
    }

    // =============================

    /**
     * 自动寻路
     *
     * @param canMoveRouteMap     过滤了无法移动的点的地图
     * @param battlefieldRouteMap 处于战斗状态的点的地图
     * @param from                出发城市
     * @param to                  到达城市
     * @return 路径，含起点终点，null表示无通路
     */
    public static List<Integer> getRouteList(Map<Integer, List<Integer>> canMoveRouteMap, Map<Integer, List<Integer>> battlefieldRouteMap, int from, int to, boolean fromIsMyCity) {
        // 优先寻路没交战的路线
        List<Integer> routeList = getRouteList(canMoveRouteMap, from, to, fromIsMyCity);
        if (routeList == null || routeList.size() <= 1) {
            // 没交战的路线寻不到则加入有战斗的城池路线
            canMoveRouteMap.putAll(battlefieldRouteMap);
            routeList = getRouteList(canMoveRouteMap, from, to, fromIsMyCity);
        }
        return routeList;
    }

    private static class Node implements Comparable<Node> {
        public final int id;
        public int cost;

        public Node(int id, int cost) {
            this.id = id;
            this.cost = cost;
        }

        @Override
        public int compareTo(Node other) {
            return Integer.compare(this.cost, other.cost);
        }
    }

    public static int getRouteListCost(Map<Integer, List<Integer>> canMoveRouteMap,
                                       int from, int to, boolean fromIsMyCity) {
        return CalcRouteCost(getRouteList(canMoveRouteMap, from, to, fromIsMyCity));
    }

    public static int CalcRouteCost(List<Integer> route) {
        if (route == null || route.isEmpty()) {
            return 0;
        }
        int ret = 0;
        for (int i = 0; i < route.size() && i + 1 < route.size(); i++) {
            ret += costSoFar.get(route.get(i) + "_" + route.get(i + 1));
        }
        return ret;
    }

    /**
     * Represents a route to a city with accumulated cost.
     */
    static class RouteNode implements Comparable<RouteNode> {
        int city;
        int cost;
        List<Integer> path;

        public RouteNode(int city, int cost, List<Integer> path) {
            this.city = city;
            this.cost = cost;
            this.path = new ArrayList<>(path);
        }

        @Override
        public int compareTo(RouteNode other) {
            return Integer.compare(this.cost, other.cost);
        }
    }

    /**
     * 自动寻路
     *
     * @param canMoveRouteMap     过滤了无法移动的点的地图
     * @param from                出发城市
     * @param to                  到达城市
     * @return 路径，含起点终点，null表示无通路
     */
    public static List<Integer> getRouteList(Map<Integer, List<Integer>> canMoveRouteMap,
                                             int from, int to, boolean fromIsMyCity) {
        Map<Integer, RouteNode> visited = new HashMap<>();
        PriorityQueue<RouteNode> queue = new PriorityQueue<>();

        List<Integer> canMoveList = new ArrayList<>(canMoveRouteMap.keySet());
        if (!fromIsMyCity) {
            canMoveList.remove((Integer) from);
        }

        // 添加起点
        visited.put(from, new RouteNode(from, 0, Collections.singletonList(from)));
        queue.offer(new RouteNode(from, 0, Collections.emptyList()));

        while (!queue.isEmpty()) {
            RouteNode current = queue.poll();

            // 找到终点，构建并返回路径
            if (current.city == to
                    && (canMoveList.contains(to) || canMoveList.contains(current.path.get(current.path.size() - 1)))) {
                List<Integer> result = new ArrayList<>(current.path);
                result.add(to);
                return result;
            }

            // 遍历连接点
            List<Integer> nextCities = canMoveRouteMap.get(current.city);
            if (nextCities == null || nextCities.isEmpty()) {
                continue;
            }

            for (Integer nextCity : nextCities) {
                if (current.city == from && !fromIsMyCity) {
                    // 初始节点非己方，则过滤一下邻居节点（非己方的过滤掉）
                    if (!canMoveList.contains(nextCity)) {
                        continue;
                    }
                }
                int newCost = current.cost + costSoFar.getOrDefault(current.city + "_" + nextCity, 0);
                if (!visited.containsKey(nextCity) || visited.get(nextCity).cost > newCost) {
                    List<Integer> newPath = new ArrayList<>(current.path);
                    newPath.add(current.city);
                    RouteNode nextNode = new RouteNode(nextCity, newCost, newPath);

                    queue.offer(nextNode);
                    visited.put(nextCity, nextNode);
                }
            }
        }

        // 没找到
        return null;
    }

    /**
     * 获取阵营中间城市地点
     */
    public static List<Integer> getMiddleCityId(Map<Integer, List<Integer>> cityConnectMap, Set<Integer> camp1PosSet, Set<Integer> camp2PosSet) {
        Set<Integer> lastPosSet = new HashSet<>(); // 走过的点
        List<List<Integer>> lastResultList = new ArrayList<>(); // 多条路线

        Set<Integer> curPosSet = new HashSet<>();
        List<List<Integer>> curResultList = new ArrayList<>(); // 多条路线

        // 准备数据
        lastPosSet.addAll(camp1PosSet);
        for (Integer pos : camp1PosSet) {
            lastResultList.add(Collections.singletonList(pos));
        }

        // 处理
        for (int i = 0; i < 99999; i++) {

            // 找每条可以走的路走一格
            for (List<Integer> route : lastResultList) {
                List<Integer> linked = cityConnectMap.get(route.get(route.size() - 1));
                for (Integer linkedPos : linked) {
                    if (lastPosSet.contains(linkedPos)) {
                        continue;
                    }
                    if (camp1PosSet.contains(linkedPos)) {
                        continue;
                    }
                    ArrayList<Integer> newRoute = new ArrayList<>(route);
                    newRoute.add(linkedPos);
                    curResultList.add(newRoute);
                    curPosSet.add(linkedPos);
                }
            }

            // 无路可走
            if (curResultList.isEmpty()) {
                break;
            }

            // 看看有没有结果
            List<List<Integer>> finalResult = new ArrayList<>();
            for (List<Integer> route : curResultList) {
                if (camp2PosSet.contains(route.get(route.size() - 1))) {
                    finalResult.add(route);
                }
            }

            // 有结果返回
            if (!finalResult.isEmpty()) {

                List<Integer> list = new ArrayList<>();

                // 多个结果都要返回
                for (List<Integer> tmpList : finalResult) {

                    int posIndex = tmpList.size() / 2;
                    list.add(tmpList.get(posIndex)); // 中点

                    if (tmpList.size() % 2 == 0) { // 有两个中点
                        posIndex = posIndex - 1;
                        list.add(tmpList.get(posIndex));
                    }
                }

                return list;
            }

            // 没结果继续找
            lastPosSet = curPosSet;
            lastResultList = curResultList;
            curResultList = new ArrayList<>();
            curPosSet = lastPosSet;
        }

        // 容错返回
        System.err.println("出bug了啊啊啊啊啊啊啊getMiddleCityId");
        return new ArrayList<>(new Random().nextDouble() > 0.5 ? camp1PosSet : camp2PosSet);
    }

}
